#pragma once
#include<functional>
namespace mutou
{
	template<class T>
	class shared_ptr
	{
	public:
		shared_ptr(T* ptr=nullptr)
			:_ptr(ptr)
			,use_count(new int(1))
		{

		}
		void release()
		{
			if (--(*use_count) == 0)
			{
				_del(_ptr);
				delete use_count;
			}
		}
		template <class D>
		shared_ptr(T* ptr , D del)
			:_ptr(ptr)
			, use_count(new int(1))
			,_del(del)
		{

		}
		shared_ptr(const shared_ptr& sp)
		{
			_ptr = sp._ptr;
			use_count = sp.use_count;
			++(*(use_count));
		}
		~shared_ptr()
		{
			release();
		}

		shared_ptr<T>& operator=(const shared_ptr<T>& sp)
		{
			if (_ptr != sp._ptr)
			{
				release();
				_ptr = sp._ptr;
				use_count = sp.use_count;
				(*(use_count))++;
			}
			return *this;
		}
		T& operator*()
		{
			return *_ptr;
		}
		T* operator->()
		{
			return _ptr;
		}
		T* get()
		{
			return _ptr;
		}
		operator bool()
		{
			return _ptr == nullptr;
		}
	private:
		T* _ptr;
		int* use_count;
		function<void(T*)> _del = [](T* t){delete t; };
	};
}
